home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 2010 April / PCWorld0410.iso / hity wydania / Ubuntu 9.10 PL / karmelkowy-koliberek-9.10-netbook-remix-PL.iso / casper / filesystem.squashfs / usr / lib / firefox-3.5.5 / components / nsPrivateBrowsingService.js < prev    next >
Text File  |  2009-11-09  |  18KB  |  501 lines

  1. //@line 38 "/build/buildd/firefox-3.5-3.5.5+nobinonly/build-tree/mozilla/browser/components/privatebrowsing/src/nsPrivateBrowsingService.js"
  2.  
  3. Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
  4.  
  5. ////////////////////////////////////////////////////////////////////////////////
  6. //// Utilities
  7.  
  8. /**
  9.  * Returns true if the string passed in is part of the root domain of the
  10.  * current string.  For example, if this is "www.mozilla.org", and we pass in
  11.  * "mozilla.org", this will return true.  It would return false the other way
  12.  * around.
  13.  */
  14. String.prototype.hasRootDomain = function hasRootDomain(aDomain)
  15. {
  16.   let index = this.indexOf(aDomain);
  17.   // If aDomain is not found, we know we do not have it as a root domain.
  18.   if (index == -1)
  19.     return false;
  20.  
  21.   // If the strings are the same, we obviously have a match.
  22.   if (this == aDomain)
  23.     return true;
  24.  
  25.   // Otherwise, we have aDomain as our root domain iff the index of aDomain is
  26.   // aDomain.length subtracted from our length and (since we do not have an
  27.   // exact match) the character before the index is a dot or slash.
  28.   let prevChar = this[index - 1];
  29.   return (index == (this.length - aDomain.length)) &&
  30.          (prevChar == "." || prevChar == "/");
  31. }
  32.  
  33. ////////////////////////////////////////////////////////////////////////////////
  34. //// Constants
  35.  
  36. const Cc = Components.classes;
  37. const Ci = Components.interfaces;
  38. const Cu = Components.utils;
  39. const Cr = Components.results;
  40.  
  41. ////////////////////////////////////////////////////////////////////////////////
  42. //// PrivateBrowsingService
  43.  
  44. function PrivateBrowsingService() {
  45.   this._obs.addObserver(this, "profile-after-change", true);
  46.   this._obs.addObserver(this, "quit-application-granted", true);
  47.   this._obs.addObserver(this, "private-browsing", true);
  48. }
  49.  
  50. PrivateBrowsingService.prototype = {
  51.   // Observer Service
  52.   __obs: null,
  53.   get _obs() {
  54.     if (!this.__obs)
  55.       this.__obs = Cc["@mozilla.org/observer-service;1"].
  56.                    getService(Ci.nsIObserverService);
  57.     return this.__obs;
  58.   },
  59.  
  60.   // Preferences Service
  61.   __prefs: null,
  62.   get _prefs() {
  63.     if (!this.__prefs)
  64.       this.__prefs = Cc["@mozilla.org/preferences-service;1"].
  65.                      getService(Ci.nsIPrefBranch);
  66.     return this.__prefs;
  67.   },
  68.  
  69.   // Whether the private browsing mode is currently active or not.
  70.   _inPrivateBrowsing: false,
  71.  
  72.   // Saved browser state before entering the private mode.
  73.   _savedBrowserState: null,
  74.  
  75.   // Whether we're in the process of shutting down
  76.   _quitting: false,
  77.  
  78.   // How to treat the non-private session
  79.   _saveSession: true,
  80.  
  81.   // Make sure we don't allow re-enterant changing of the private mode
  82.   _alreadyChangingMode: false,
  83.  
  84.   // Whether we're entering the private browsing mode at application startup
  85.   _autoStart: false,
  86.  
  87.   // Whether the private browsing mode has been started automatically
  88.   _autoStarted: false,
  89.  
  90.   // XPCOM registration
  91.   classDescription: "PrivateBrowsing Service",
  92.   contractID: "@mozilla.org/privatebrowsing;1",
  93.   classID: Components.ID("{c31f4883-839b-45f6-82ad-a6a9bc5ad599}"),
  94.   _xpcom_categories: [
  95.     { category: "app-startup", service: true }
  96.   ],
  97.  
  98.   QueryInterface: XPCOMUtils.generateQI([Ci.nsIPrivateBrowsingService, 
  99.                                          Ci.nsIObserver,
  100.                                          Ci.nsISupportsWeakReference]),
  101.  
  102.   _unload: function PBS__destroy() {
  103.     // Force an exit from the private browsing mode on shutdown
  104.     this._quitting = true;
  105.     if (this._inPrivateBrowsing)
  106.       this.privateBrowsingEnabled = false;
  107.   },
  108.  
  109.   _onBeforePrivateBrowsingModeChange: function PBS__onBeforePrivateBrowsingModeChange() {
  110.     // nothing needs to be done here if we're auto-starting
  111.     if (!this._autoStart) {
  112.       let ss = Cc["@mozilla.org/browser/sessionstore;1"].
  113.                getService(Ci.nsISessionStore);
  114.       let blankState = JSON.stringify({
  115.         "windows": [{
  116.           "tabs": [{
  117.             "entries": [{
  118.               "url": "about:blank"
  119.             }]
  120.           }],
  121.           "_closedTabs": []
  122.         }]
  123.       });
  124.  
  125.       // whether we should save and close the current session
  126.       this._saveSession = true;
  127.       try {
  128.         if (this._prefs.getBoolPref("browser.privatebrowsing.keep_current_session"))
  129.           this._saveSession = false;
  130.       } catch (ex) {}
  131.  
  132.       if (this._inPrivateBrowsing) {
  133.         // save the whole browser state in order to restore all windows/tabs later
  134.         if (this._saveSession && !this._savedBrowserState) {
  135.           if (this._getBrowserWindow())
  136.             this._savedBrowserState = ss.getBrowserState();
  137.           else // no open browser windows, just restore a blank state on exit
  138.             this._savedBrowserState = blankState;
  139.         }
  140.       }
  141.  
  142.       this._closePageInfoWindows();
  143.  
  144.       if (!this._quitting && this._saveSession) {
  145.         let browserWindow = this._getBrowserWindow();
  146.  
  147.         // if there are open browser windows, load a dummy session to get a distinct 
  148.         // separation between private and non-private sessions
  149.         if (browserWindow) {
  150.           // set an empty session to transition from/to pb mode, see bug 476463
  151.           ss.setBrowserState(blankState);
  152.  
  153.           // just in case the only remaining window after setBrowserState is different.
  154.           // it probably shouldn't be with the current sessionstore impl, but we shouldn't
  155.           // rely on behaviour the API doesn't guarantee
  156.           let browser = this._getBrowserWindow().gBrowser;
  157.  
  158.           // this ensures a clean slate from which to transition into or out of
  159.           // private browsing
  160.           browser.addTab();
  161.           browser.removeTab(browser.tabContainer.firstChild);
  162.         }
  163.       }
  164.     }
  165.     else
  166.       this._saveSession = false;
  167.   },
  168.  
  169.   _onAfterPrivateBrowsingModeChange: function PBS__onAfterPrivateBrowsingModeChange() {
  170.     // nothing to do here if we're auto-starting or the current session is being
  171.     // used
  172.     if (!this._autoStart && this._saveSession) {
  173.       let ss = Cc["@mozilla.org/browser/sessionstore;1"].
  174.                getService(Ci.nsISessionStore);
  175.       // if we have transitioned out of private browsing mode and the session is
  176.       // to be restored, do it now
  177.       if (!this._inPrivateBrowsing) {
  178.         ss.setBrowserState(this._savedBrowserState);
  179.         this._savedBrowserState = null;
  180.  
  181.         this._closePageInfoWindows();
  182.       }
  183.       else {
  184.         // otherwise, if we have transitioned into private browsing mode, load
  185.         // about:privatebrowsing
  186.         let privateBrowsingState = {
  187.           "windows": [{
  188.             "tabs": [{
  189.               "entries": [{
  190.                 "url": "about:privatebrowsing"
  191.               }]
  192.             }],
  193.             "_closedTabs": []
  194.           }]
  195.         };
  196.         // Transition into private browsing mode
  197.         ss.setBrowserState(JSON.stringify(privateBrowsingState));
  198.       }
  199.     }
  200.   },
  201.  
  202.   _canEnterPrivateBrowsingMode: function PBS__canEnterPrivateBrowsingMode() {
  203.     let cancelEnter = Cc["@mozilla.org/supports-PRBool;1"].
  204.                       createInstance(Ci.nsISupportsPRBool);
  205.     cancelEnter.data = false;
  206.     this._obs.notifyObservers(cancelEnter, "private-browsing-cancel-vote", "enter");
  207.     return !cancelEnter.data;
  208.   },
  209.  
  210.   _canLeavePrivateBrowsingMode: function PBS__canLeavePrivateBrowsingMode() {
  211.     let cancelLeave = Cc["@mozilla.org/supports-PRBool;1"].
  212.                       createInstance(Ci.nsISupportsPRBool);
  213.     cancelLeave.data = false;
  214.     this._obs.notifyObservers(cancelLeave, "private-browsing-cancel-vote", "exit");
  215.     return !cancelLeave.data;
  216.   },
  217.  
  218.   _getBrowserWindow: function PBS__getBrowserWindow() {
  219.     return Cc["@mozilla.org/appshell/window-mediator;1"].
  220.            getService(Ci.nsIWindowMediator).
  221.            getMostRecentWindow("navigator:browser");
  222.   },
  223.  
  224.   _closePageInfoWindows: function PBS__closePageInfoWindows() {
  225.     let pageInfoEnum = Cc["@mozilla.org/appshell/window-mediator;1"].
  226.                        getService(Ci.nsIWindowMediator).
  227.                        getEnumerator("Browser:page-info");
  228.     while (pageInfoEnum.hasMoreElements()) {
  229.       let win = pageInfoEnum.getNext();
  230.       win.close();
  231.     }
  232.   },
  233.  
  234.   // nsIObserver
  235.  
  236.   observe: function PBS_observe(aSubject, aTopic, aData) {
  237.     switch (aTopic) {
  238.       case "profile-after-change":
  239.         // If the autostart prefs has been set, simulate entering the
  240.         // private browsing mode upon startup.
  241.         // This won't interfere with the session store component, because
  242.         // that component will be initialized on final-ui-startup.
  243.         this._autoStart = this._prefs.getBoolPref("browser.privatebrowsing.autostart");
  244.         if (this._autoStart) {
  245.           this._autoStarted = true;
  246.           this.privateBrowsingEnabled = true;
  247.           this._autoStart = false;
  248.         }
  249.         this._obs.removeObserver(this, "profile-after-change");
  250.         break;
  251.       case "quit-application-granted":
  252.         this._unload();
  253.         break;
  254.       case "private-browsing":
  255.         // clear all auth tokens
  256.         let sdr = Cc["@mozilla.org/security/sdr;1"].
  257.                   getService(Ci.nsISecretDecoderRing);
  258.         sdr.logoutAndTeardown();
  259.     
  260.         // clear plain HTTP auth sessions
  261.         let authMgr = Cc['@mozilla.org/network/http-auth-manager;1'].
  262.                       getService(Ci.nsIHttpAuthManager);
  263.         authMgr.clearAll();
  264.  
  265.         if (!this._inPrivateBrowsing) {
  266.           // Clear the error console
  267.           let consoleService = Cc["@mozilla.org/consoleservice;1"].
  268.                                getService(Ci.nsIConsoleService);
  269.           consoleService.logStringMessage(null); // trigger the listeners
  270.           consoleService.reset();
  271.         }
  272.         break;
  273.     }
  274.   },
  275.  
  276.   // nsIPrivateBrowsingService
  277.  
  278.   /**
  279.    * Return the current status of private browsing.
  280.    */
  281.   get privateBrowsingEnabled PBS_get_privateBrowsingEnabled() {
  282.     return this._inPrivateBrowsing;
  283.   },
  284.  
  285.   /**
  286.    * Enter or leave private browsing mode.
  287.    */
  288.   set privateBrowsingEnabled PBS_set_privateBrowsingEnabled(val) {
  289.     // Allowing observers to set the private browsing status from their
  290.     // notification handlers is not desired, because it will change the
  291.     // status of the service while it's in the process of another transition.
  292.     // So, we detect a reentrant call here and throw an error.
  293.     // This is documented in nsIPrivateBrowsingService.idl.
  294.     if (this._alreadyChangingMode)
  295.       throw Cr.NS_ERROR_FAILURE;
  296.  
  297.     try {
  298.       this._alreadyChangingMode = true;
  299.  
  300.       if (val != this._inPrivateBrowsing) {
  301.         if (val) {
  302.           if (!this._canEnterPrivateBrowsingMode())
  303.             return;
  304.         }
  305.         else {
  306.           if (!this._canLeavePrivateBrowsingMode())
  307.             return;
  308.         }
  309.  
  310.         this._autoStarted = val ?
  311.           this._prefs.getBoolPref("browser.privatebrowsing.autostart") : false;
  312.         this._inPrivateBrowsing = val != false;
  313.  
  314.         let data = val ? "enter" : "exit";
  315.  
  316.         let quitting = Cc["@mozilla.org/supports-PRBool;1"].
  317.                        createInstance(Ci.nsISupportsPRBool);
  318.         quitting.data = this._quitting;
  319.  
  320.         // notify observers of the pending private browsing mode change
  321.         this._obs.notifyObservers(quitting, "private-browsing-change-granted", data);
  322.  
  323.         // destroy the current session and start initial cleanup
  324.         this._onBeforePrivateBrowsingModeChange();
  325.  
  326.         this._obs.notifyObservers(quitting, "private-browsing", data);
  327.  
  328.         // load the appropriate session
  329.         this._onAfterPrivateBrowsingModeChange();
  330.       }
  331.     } catch (ex) {
  332.       Cu.reportError("Exception thrown while processing the " +
  333.         "private browsing mode change request: " + ex.toString());
  334.     } finally {
  335.       this._alreadyChangingMode = false;
  336.     }
  337.   },
  338.  
  339.   /**
  340.    * Whether private browsing has been started automatically.
  341.    */
  342.   get autoStarted PBS_get_autoStarted() {
  343.     return this._autoStarted;
  344.   },
  345.  
  346.   removeDataFromDomain: function PBS_removeDataFromDomain(aDomain)
  347.   {
  348.  
  349.     // clear any and all network geolocation provider sessions
  350.     try {
  351.         this._prefs.deleteBranch("geo.wifi.access_token.");
  352.     } catch (e) {}
  353.     
  354.     // History
  355.     let (bh = Cc["@mozilla.org/browser/global-history;2"].
  356.               getService(Ci.nsIBrowserHistory)) {
  357.       bh.removePagesFromHost(aDomain, true);
  358.     }
  359.  
  360.     // Cache
  361.     let (cs = Cc["@mozilla.org/network/cache-service;1"].
  362.               getService(Ci.nsICacheService)) {
  363.       // NOTE: there is no way to clear just that domain, so we clear out
  364.       //       everything)
  365.       try {
  366.         cs.evictEntries(Ci.nsICache.STORE_ANYWHERE);
  367.       } catch (ex) {
  368.         Cu.reportError("Exception thrown while clearing the cache: " +
  369.           ex.toString());
  370.       }
  371.     }
  372.  
  373.     // Cookies
  374.     let (cm = Cc["@mozilla.org/cookiemanager;1"].
  375.               getService(Ci.nsICookieManager)) {
  376.       let enumerator = cm.enumerator;
  377.       while (enumerator.hasMoreElements()) {
  378.         let cookie = enumerator.getNext().QueryInterface(Ci.nsICookie);
  379.         if (cookie.host.hasRootDomain(aDomain))
  380.           cm.remove(cookie.host, cookie.name, cookie.path, false);
  381.       }
  382.     }
  383.  
  384.     // Downloads
  385.     let (dm = Cc["@mozilla.org/download-manager;1"].
  386.               getService(Ci.nsIDownloadManager)) {
  387.       // Active downloads
  388.       let enumerator = dm.activeDownloads;
  389.       while (enumerator.hasMoreElements()) {
  390.         let dl = enumerator.getNext().QueryInterface(Ci.nsIDownload);
  391.         if (dl.source.host.hasRootDomain(aDomain)) {
  392.           dm.cancelDownload(dl.id);
  393.           dm.removeDownload(dl.id);
  394.         }
  395.       }
  396.  
  397.       // Completed downloads
  398.       let db = dm.DBConnection;
  399.       // NOTE: This is lossy, but we feel that it is OK to be lossy here and not
  400.       //       invoke the cost of creating a URI for each download entry and
  401.       //       ensure that the hostname matches.
  402.       let stmt = db.createStatement(
  403.         "DELETE FROM moz_downloads " +
  404.         "WHERE source LIKE ?1 ESCAPE '/' " +
  405.         "AND state NOT IN (?2, ?3, ?4)"
  406.       );
  407.       let pattern = stmt.escapeStringForLIKE(aDomain, "/");
  408.       stmt.bindStringParameter(0, "%" + pattern + "%");
  409.       stmt.bindInt32Parameter(1, Ci.nsIDownloadManager.DOWNLOAD_DOWNLOADING);
  410.       stmt.bindInt32Parameter(2, Ci.nsIDownloadManager.DOWNLOAD_PAUSED);
  411.       stmt.bindInt32Parameter(3, Ci.nsIDownloadManager.DOWNLOAD_QUEUED);
  412.       try {
  413.         stmt.execute();
  414.       }
  415.       finally {
  416.         stmt.finalize();
  417.       }
  418.  
  419.       // We want to rebuild the list if the UI is showing, so dispatch the
  420.       // observer topic
  421.       let os = Cc["@mozilla.org/observer-service;1"].
  422.                getService(Ci.nsIObserverService);
  423.       os.notifyObservers(null, "download-manager-remove-download", null);
  424.     }
  425.  
  426.     // Passwords
  427.     let (lm = Cc["@mozilla.org/login-manager;1"].
  428.               getService(Ci.nsILoginManager)) {
  429.       // Clear all passwords for domain
  430.       try {
  431.         let logins = lm.getAllLogins({});
  432.         for (let i = 0; i < logins.length; i++)
  433.           if (logins[i].hostname.hasRootDomain(aDomain))
  434.             lm.removeLogin(logins[i]);
  435.       }
  436.       // XXXehsan: is there a better way to do this rather than this
  437.       // hacky comparison?
  438.       catch (ex if ex.message.indexOf("User canceled Master Password entry") != -1) { }
  439.  
  440.       // Clear any "do not save for this site" for this domain
  441.       let disabledHosts = lm.getAllDisabledHosts({});
  442.       for (let i = 0; i < disabledHosts.length; i++)
  443.         if (disabledHosts[i].hasRootDomain(aDomain))
  444.           lm.setLoginSavingEnabled(disabledHosts, true);
  445.     }
  446.  
  447.     // Permissions
  448.     let (pm = Cc["@mozilla.org/permissionmanager;1"].
  449.               getService(Ci.nsIPermissionManager)) {
  450.       // Enumerate all of the permissions, and if one matches, remove it
  451.       let enumerator = pm.enumerator;
  452.       while (enumerator.hasMoreElements()) {
  453.         let perm = enumerator.getNext().QueryInterface(Ci.nsIPermission);
  454.         if (perm.host.hasRootDomain(aDomain))
  455.           pm.remove(perm.host, perm.type);
  456.       }
  457.     }
  458.  
  459.     // Content Preferences
  460.     let (cp = Cc["@mozilla.org/content-pref/service;1"].
  461.               getService(Ci.nsIContentPrefService)) {
  462.       let db = cp.DBConnection;
  463.       // First we need to get the list of "groups" which are really just domains
  464.       let names = [];
  465.       let stmt = db.createStatement(
  466.         "SELECT name " +
  467.         "FROM groups " +
  468.         "WHERE name LIKE ?1 ESCAPE '/'"
  469.       );
  470.       let pattern = stmt.escapeStringForLIKE(aDomain, "/");
  471.       stmt.bindStringParameter(0, "%" + pattern);
  472.       try {
  473.         while (stmt.executeStep())
  474.           if (stmt.getString(0).hasRootDomain(aDomain))
  475.             names.push(stmt.getString(0));
  476.       }
  477.       finally {
  478.         stmt.finalize();
  479.       }
  480.  
  481.       // Now, for each name we got back, remove all of its prefs.
  482.       for (let i = 0; i < names.length; i++) {
  483.         // The service only cares about the host of the URI, so we don't need a
  484.         // full nsIURI object here.
  485.         let uri = { host: names[i]};
  486.         let enumerator = cp.getPrefs(uri).enumerator;
  487.         while (enumerator.hasMoreElements()) {
  488.           let pref = enumerator.getNext().QueryInterface(Ci.nsIProperty);
  489.           cp.removePref(uri, pref.name);
  490.         }
  491.       }
  492.     }
  493.  
  494.     // Everybody else (including extensions)
  495.     this._obs.notifyObservers(null, "browser:purge-domain-data", aDomain);
  496.   }
  497. };
  498.  
  499. function NSGetModule(compMgr, fileSpec)
  500.   XPCOMUtils.generateModule([PrivateBrowsingService]);
  501.